﻿using cfg;
using Cinemachine;
using Script;
using UnityEngine;
using UnityEngine.InputSystem;

namespace DoDove
{
    public class GameplayCameraHandler : ICameraHandler
    {
        public GameObject _cameraPrefab;

        private float _deadZoneWidthRatio = 0.85f;

        private float _deadZoneHeightRatio = 0.85f;

        // 相机移动的基础速度
        private float _cameraMoveSpeed = 15f;

        private Rect _gameViewRect;

        private Vector2 _gameViewCenter;

        // 缓存计算出的死区半尺寸（像素）
        private Vector2 _halfDeadZoneSize;

        //计算是否被铺满
        private bool _isXAxisFilledCached = false;
        private bool _isYAxisFilledCached = false;


        public Vector2 HalfDeadZoneSize => _halfDeadZoneSize;
        private Vector2 _cameraHalfExtents = Vector2.zero;
        private GameObject _cameraGameObject;
        private GameObject _gameplayCameraTargetObj;
        private CinemachineVirtualCamera _cinemachineVirtualCamera;
        private string _cameraName;

        public GameplayCameraHandler()
        {
            var config = GameConfigKit.Instance.gameConfig.TbGamePlayCamera;

            _cameraName = config.CameraName;
            _cameraPrefab = ResKit.Instance.GetResByResName<GameObject>("Prefab/Camera", config.CameraName);

            _deadZoneWidthRatio = config.DeadZoneRatio.X;
            _deadZoneHeightRatio = config.DeadZoneRatio.Y;
            _cameraMoveSpeed = config.CameraMoveSpeed;
            SetupScreenAreas();
            SetUpTitleMapFillScreenStated();
            SetUpCameraTargetObj();
            RegisterCameraHandler();
        }

        //构造 GamePlay Camera软区 死区Z  todo : 后面屏幕改变 或者地图改变要重新
        public void SetupScreenAreas()
        {
            _gameViewRect = Camera.main.pixelRect;

            // 2. 计算Game视图的中心点
            _gameViewCenter = _gameViewRect.center;

            // 3. 根据Game视图的尺寸和预设的比例，计算死区的实际像素大小
            float deadZoneWidth = _gameViewRect.width * _deadZoneWidthRatio;
            float deadZoneHeight = _gameViewRect.height * _deadZoneHeightRatio;
            _halfDeadZoneSize = new Vector2(deadZoneWidth / 2f, deadZoneHeight / 2f);

            //计算内收
            Camera mainCam = Camera.main;
            float orthoSize = mainCam.orthographicSize; // 垂直半高（中心到顶部的距离）
            float aspectRatio = mainCam.aspect; // 宽高比（如16:9为~1.777）

            // 水平半宽 = 垂直半高 × 宽高比
            float halfWidth = orthoSize * aspectRatio;
            float halfHeight = orthoSize;
            _cameraHalfExtents = new Vector3(halfWidth, halfHeight, 0);
        }

        // 地图铺满状态的计算逻辑
        public void SetUpTitleMapFillScreenStated()
        {
            var titlemapWorldBounds = TileMapKit.Instance.GetTitlemapWorldBounds();
            float mapSizeX = titlemapWorldBounds.max.x - titlemapWorldBounds.min.x;
            float mapSizeY = titlemapWorldBounds.max.y - titlemapWorldBounds.min.y;

            // 使用 _cameraHalfExtents，它在 SetupScreenAreas 中已经计算好了
            float cameraViewSizeX = _cameraHalfExtents.x * 2;
            float cameraViewSizeY = _cameraHalfExtents.y * 2;

            // 更新缓存的状态
            _isXAxisFilledCached = mapSizeX >= cameraViewSizeX;
            _isYAxisFilledCached = mapSizeY >= cameraViewSizeY;
        }

        public void SetUpCameraTargetObj()
        {
            //从创建的实例中获取对应跟随对象
            if (_cameraGameObject == null)
            {
                _cameraGameObject = Object.Instantiate(_cameraPrefab);
            }

            for (int i = 0; i < _cameraGameObject.transform.childCount; i++)
            {
                // 4. 通过索引获取子节点的 Transform
                Transform childTransform = _cameraGameObject.transform.GetChild(i);

                if (childTransform.name == _cameraName + "TargetObj")
                {
                    _gameplayCameraTargetObj = childTransform.gameObject;
                }

                break;
            }

            _cinemachineVirtualCamera = _cameraGameObject.GetComponentInChildren<CinemachineVirtualCamera>();
        }


        public void MoveTargetObj()
        {
            Vector3 moveDirection = CalculateEdgeMoveVector(Mouse.current.position.ReadValue());

            // 恒定速度移动（类似LoL的平滑边缘移动）
            Vector3 moveDelta = moveDirection * _cameraMoveSpeed * Time.deltaTime;
            //先计算位置
            Vector3 targetPosition = _gameplayCameraTargetObj.transform.localPosition + moveDelta;
            // 边界限制
            ClampTargetToTilemapBounds(targetPosition);
        }

        private Vector3 CalculateEdgeMoveVector(Vector2 mouseScreenPosition)
        {
            Vector3 moveVector = Vector3.zero;

            if (!_gameViewRect.Contains(mouseScreenPosition))
                return moveVector;


            // 计算死区边界
            // 计算死区边界
            float deadZoneLeft = _gameViewCenter.x - _halfDeadZoneSize.x;
            float deadZoneRight = _gameViewCenter.x + _halfDeadZoneSize.x;
            float deadZoneBottom = _gameViewCenter.y - _halfDeadZoneSize.y;
            float deadZoneTop = _gameViewCenter.y + _halfDeadZoneSize.y;

            // 只在真正边缘区域触发移动
            bool isAtLeftEdge = mouseScreenPosition.x <= deadZoneLeft;
            bool isAtRightEdge = mouseScreenPosition.x >= deadZoneRight;
            bool isAtTopEdge = mouseScreenPosition.y >= deadZoneTop;
            bool isAtBottomEdge = mouseScreenPosition.y <= deadZoneBottom;

            // X轴移动（左/右边缘）
            if (isAtLeftEdge)
                moveVector.x = -1f; // 向左移动
            else if (isAtRightEdge)
                moveVector.x = 1f; // 向右移动


            // Z轴移动（上/下边缘）- 俯视角对应前后移动
            if (isAtTopEdge)
                moveVector.y = 1f; // "向前"移动（相机看向的方向）
            else if (isAtBottomEdge)
                moveVector.y = -1f; // "向后"移动


            if (!_isXAxisFilledCached)
            {
                moveVector.x = 0f; // X轴未铺满，强制X方向移动为0
            }

            if (!_isYAxisFilledCached)
            {
                moveVector.y = 0f; // Y轴未铺满，强制Y方向移动为0
            }

            return moveVector;
        }

        private void ClampTargetToTilemapBounds(Vector3 targetPosition)
        {
            if (_gameplayCameraTargetObj == null) return;

            var titlemapWorldBounds = TileMapKit.Instance.GetTitlemapWorldBounds();

            //计算补正 瓦片地图会因为瓦片数量的关系导致瓦片中心可能不是0,0 的情况 0 - center的偏移量  
            Vector3 correct = titlemapWorldBounds.center - Vector3.zero;
            float positiveCorrectX = correct.x / 2;
            float negativeCorrectX = -correct.x / 2;
            float positiveCorrectY = correct.y / 2;
            float negativeCorrectY = -correct.y / 2;

            // 计算精确的边界（移除硬编码的 ±1，用相机半宽/半高）
            float minX = titlemapWorldBounds.min.x + _cameraHalfExtents.x + negativeCorrectX;
            float maxX = titlemapWorldBounds.max.x - _cameraHalfExtents.x + positiveCorrectX;
            float minY = titlemapWorldBounds.min.y + _cameraHalfExtents.y + negativeCorrectY;
            float maxY = titlemapWorldBounds.max.y - _cameraHalfExtents.y + positiveCorrectY;

            // 处理「地图比相机视野小」的情况：此时边界设为地图本身范围
            if (maxX < minX) maxX = minX;
            if (maxY < minY) maxY = minY;

            // 初始化为目标位置（未铺满时不修改）
            Vector3 clampedPos = targetPosition;

            // 仅在轴铺满时，才执行Clamp
            if (_isXAxisFilledCached)
            {
                clampedPos.x = Mathf.Clamp(targetPosition.x, minX, maxX);
            }

            if (_isYAxisFilledCached)
            {
                clampedPos.y = Mathf.Clamp(targetPosition.y, minY, maxY);
            }
            
            _gameplayCameraTargetObj.transform.localPosition = clampedPos;
        }

        public void MoveToCenter()
        {
            _gameplayCameraTargetObj.transform.localPosition = Vector3.zero;
        }

        public string GetCameraName()
        {
            return _cameraName;
        }

        public GameObject GetCameraObject()
        {
            return _cameraGameObject;
        }

        public CinemachineVirtualCamera GetVirtualCamera()
        {
            return _cinemachineVirtualCamera;
        }

        public void RegisterCameraHandler()
        {
            CameraManager.Instance.RegisterVirtualCamera(this);
        }
    }
}